using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using System.Timers;
using Domain.Items;
using ServiceDeclaration;
using Task = Domain.Items.Task;

namespace ServiceImplementation
{
    public class ApplicationManager:IApplicationManager
    {

        private IDictionary<Timer, Task> taskCache;

        public ApplicationManager()
        {
            taskCache = new Dictionary<Timer, Task>();
        }

        public void RemoveTaskFromQueue(Task task)
        {
            var processInCache = taskCache.FirstOrDefault(x => x.Value.Id == task.Id);
            processInCache.Key.Stop();
            taskCache.Remove(processInCache);
        }

        public IEnumerable<Task> GetTasksInQueue()
        {
            return taskCache.Select(x=>x.Value);
        }

        public bool QueueTask(Task task)
        {
            var dateDiff = (task.LaunchTime - DateTime.Now);
            var timer = InitializeTimerWithLength(dateDiff);

            taskCache.Add(timer, task);

            StartTimerWithoutFirstTick(timer);
            return true;
        }

        private void Launch(Application application)
        {
            Process process = new Process();
            try
            {
                process.StartInfo.FileName = application.Path;
                process.Start();
            }
            catch (Exception ex)
            {
                return;
            }
        }

        private static Timer InitializeTimerWithLength(TimeSpan dateDiff)
        {
            var timeInMilliseconds = dateDiff.TotalMilliseconds;
            return new Timer(timeInMilliseconds);
        }

        private void StartTimerWithoutFirstTick(Timer timer)
        {
            timer.Enabled = false;
            timer.Elapsed += TriggerApplicationLaunch;
            timer.Start();
            timer.Enabled = true;
        }

        private void TriggerApplicationLaunch(object sender, ElapsedEventArgs e)
        {
            var timer = sender as Timer;
            if (timer != null)
            {
                if (taskCache.ContainsKey(timer))
                {
                    var process = taskCache.FirstOrDefault(x => x.Key == timer);
                    Launch(process.Value.Application);
                    taskCache.Remove(process);
                }
                timer.Stop();
            }
        }
    }
}